/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package ccore.model.impl;

import java.util.Collection;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EObjectWithInverseResolvingEList;
import org.eclipse.emf.ecore.util.InternalEList;

import ccore.CCore;
import ccore.common.impl.CElementImpl;
import ccore.expression.CIntVar;
import ccore.instance.CObject;
import ccore.instance.InstancePackage;
import ccore.model.CClass;
import ccore.model.ModelPackage;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>CClass</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link ccore.model.impl.CClassImpl#getSuperClass <em>Super Class</em>}</li>
 *   <li>{@link ccore.model.impl.CClassImpl#getSubClasses <em>Sub Classes</em>}</li>
 *   <li>{@link ccore.model.impl.CClassImpl#isAbstract <em>Abstract</em>}</li>
 *   <li>{@link ccore.model.impl.CClassImpl#getFirstObject <em>First Object</em>}</li>
 *   <li>{@link ccore.model.impl.CClassImpl#getLastObject <em>Last Object</em>}</li>
 *   <li>{@link ccore.model.impl.CClassImpl#getCardinality <em>Cardinality</em>}</li>
 *   <li>{@link ccore.model.impl.CClassImpl#getSelfCardinality <em>Self Cardinality</em>}</li>
 *   <li>{@link ccore.model.impl.CClassImpl#getCObjects <em>CObjects</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class CClassImpl extends CElementImpl implements CClass {
	/**
	 * The cached value of the '{@link #getSuperClass() <em>Super Class</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getSuperClass()
	 * @generated
	 * @ordered
	 */
	protected CClass superClass;

	/**
	 * The cached value of the '{@link #getSubClasses() <em>Sub Classes</em>}' reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getSubClasses()
	 * @generated
	 * @ordered
	 */
	protected EList<CClass> subClasses;

	/**
	 * The default value of the '{@link #isAbstract() <em>Abstract</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isAbstract()
	 * @generated
	 * @ordered
	 */
	protected static final boolean ABSTRACT_EDEFAULT = false;

	/**
	 * The cached value of the '{@link #isAbstract() <em>Abstract</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isAbstract()
	 * @generated
	 * @ordered
	 */
	protected boolean abstract_ = ABSTRACT_EDEFAULT;

	/**
	 * The default value of the '{@link #getFirstObject() <em>First Object</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getFirstObject()
	 * @generated
	 * @ordered
	 */
	protected static final int FIRST_OBJECT_EDEFAULT = 0;

	/**
	 * The cached value of the '{@link #getFirstObject() <em>First Object</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getFirstObject()
	 * @generated
	 * @ordered
	 */
	protected int firstObject = FIRST_OBJECT_EDEFAULT;

	/**
	 * The default value of the '{@link #getLastObject() <em>Last Object</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getLastObject()
	 * @generated
	 * @ordered
	 */
	protected static final int LAST_OBJECT_EDEFAULT = 0;

	/**
	 * The cached value of the '{@link #getLastObject() <em>Last Object</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getLastObject()
	 * @generated
	 * @ordered
	 */
	protected int lastObject = LAST_OBJECT_EDEFAULT;

	/**
	 * The cached value of the '{@link #getCardinality() <em>Cardinality</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getCardinality()
	 * @generated
	 * @ordered
	 */
	protected CIntVar cardinality;

	/**
	 * The cached value of the '{@link #getSelfCardinality() <em>Self Cardinality</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getSelfCardinality()
	 * @generated
	 * @ordered
	 */
	protected CIntVar selfCardinality;

	/**
	 * The cached value of the '{@link #getCObjects() <em>CObjects</em>}' reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getCObjects()
	 * @generated
	 * @ordered
	 */
	protected EList<CObject> cObjects;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected CClassImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return ModelPackage.Literals.CCLASS;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public CClass getSuperClass() {
		if (superClass != null && superClass.eIsProxy()) {
			InternalEObject oldSuperClass = (InternalEObject)superClass;
			superClass = (CClass)eResolveProxy(oldSuperClass);
			if (superClass != oldSuperClass) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE, ModelPackage.CCLASS__SUPER_CLASS, oldSuperClass, superClass));
			}
		}
		return superClass;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public CClass basicGetSuperClass() {
		return superClass;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetSuperClass(CClass newSuperClass, NotificationChain msgs) {
		CClass oldSuperClass = superClass;
		superClass = newSuperClass;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__SUPER_CLASS, oldSuperClass, newSuperClass);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setSuperClass(CClass newSuperClass) {
		if (newSuperClass != superClass) {
			NotificationChain msgs = null;
			if (superClass != null)
				msgs = ((InternalEObject)superClass).eInverseRemove(this, ModelPackage.CCLASS__SUB_CLASSES, CClass.class, msgs);
			if (newSuperClass != null)
				msgs = ((InternalEObject)newSuperClass).eInverseAdd(this, ModelPackage.CCLASS__SUB_CLASSES, CClass.class, msgs);
			msgs = basicSetSuperClass(newSuperClass, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__SUPER_CLASS, newSuperClass, newSuperClass));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList<CClass> getSubClasses() {
		if (subClasses == null) {
			subClasses = new EObjectWithInverseResolvingEList<CClass>(CClass.class, this, ModelPackage.CCLASS__SUB_CLASSES, ModelPackage.CCLASS__SUPER_CLASS);
		}
		return subClasses;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public boolean isAbstract() {
		return abstract_;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setAbstract(boolean newAbstract) {
		boolean oldAbstract = abstract_;
		abstract_ = newAbstract;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__ABSTRACT, oldAbstract, abstract_));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public int getFirstObject() {
		return firstObject;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setFirstObject(int newFirstObject) {
		int oldFirstObject = firstObject;
		firstObject = newFirstObject;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__FIRST_OBJECT, oldFirstObject, firstObject));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public int getLastObject() {
		return lastObject;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setLastObject(int newLastObject) {
		int oldLastObject = lastObject;
		lastObject = newLastObject;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__LAST_OBJECT, oldLastObject, lastObject));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public CIntVar getCardinality() {
		return cardinality;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetCardinality(CIntVar newCardinality, NotificationChain msgs) {
		CIntVar oldCardinality = cardinality;
		cardinality = newCardinality;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__CARDINALITY, oldCardinality, newCardinality);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setCardinality(CIntVar newCardinality) {
		if (newCardinality != cardinality) {
			NotificationChain msgs = null;
			if (cardinality != null)
				msgs = ((InternalEObject)cardinality).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - ModelPackage.CCLASS__CARDINALITY, null, msgs);
			if (newCardinality != null)
				msgs = ((InternalEObject)newCardinality).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - ModelPackage.CCLASS__CARDINALITY, null, msgs);
			msgs = basicSetCardinality(newCardinality, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__CARDINALITY, newCardinality, newCardinality));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public CIntVar getSelfCardinality() {
		return selfCardinality;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetSelfCardinality(CIntVar newSelfCardinality, NotificationChain msgs) {
		CIntVar oldSelfCardinality = selfCardinality;
		selfCardinality = newSelfCardinality;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__SELF_CARDINALITY, oldSelfCardinality, newSelfCardinality);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setSelfCardinality(CIntVar newSelfCardinality) {
		if (newSelfCardinality != selfCardinality) {
			NotificationChain msgs = null;
			if (selfCardinality != null)
				msgs = ((InternalEObject)selfCardinality).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - ModelPackage.CCLASS__SELF_CARDINALITY, null, msgs);
			if (newSelfCardinality != null)
				msgs = ((InternalEObject)newSelfCardinality).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - ModelPackage.CCLASS__SELF_CARDINALITY, null, msgs);
			msgs = basicSetSelfCardinality(newSelfCardinality, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ModelPackage.CCLASS__SELF_CARDINALITY, newSelfCardinality, newSelfCardinality));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList<CObject> getCObjects() {
		if (cObjects == null) {
			cObjects = new EObjectWithInverseResolvingEList<CObject>(CObject.class, this, ModelPackage.CCLASS__COBJECTS, InstancePackage.COBJECT__CCLASS);
		}
		return cObjects;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @not generated
	 */
	public int initId(int id) {
		setId(id++);
		
		for (CClass c: getSubClasses()) {
			id = c.initId(id);
		}
		
		return id;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case ModelPackage.CCLASS__SUPER_CLASS:
				if (superClass != null)
					msgs = ((InternalEObject)superClass).eInverseRemove(this, ModelPackage.CCLASS__SUB_CLASSES, CClass.class, msgs);
				return basicSetSuperClass((CClass)otherEnd, msgs);
			case ModelPackage.CCLASS__SUB_CLASSES:
				return ((InternalEList<InternalEObject>)(InternalEList<?>)getSubClasses()).basicAdd(otherEnd, msgs);
			case ModelPackage.CCLASS__COBJECTS:
				return ((InternalEList<InternalEObject>)(InternalEList<?>)getCObjects()).basicAdd(otherEnd, msgs);
		}
		return super.eInverseAdd(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case ModelPackage.CCLASS__SUPER_CLASS:
				return basicSetSuperClass(null, msgs);
			case ModelPackage.CCLASS__SUB_CLASSES:
				return ((InternalEList<?>)getSubClasses()).basicRemove(otherEnd, msgs);
			case ModelPackage.CCLASS__CARDINALITY:
				return basicSetCardinality(null, msgs);
			case ModelPackage.CCLASS__SELF_CARDINALITY:
				return basicSetSelfCardinality(null, msgs);
			case ModelPackage.CCLASS__COBJECTS:
				return ((InternalEList<?>)getCObjects()).basicRemove(otherEnd, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case ModelPackage.CCLASS__SUPER_CLASS:
				if (resolve) return getSuperClass();
				return basicGetSuperClass();
			case ModelPackage.CCLASS__SUB_CLASSES:
				return getSubClasses();
			case ModelPackage.CCLASS__ABSTRACT:
				return isAbstract() ? Boolean.TRUE : Boolean.FALSE;
			case ModelPackage.CCLASS__FIRST_OBJECT:
				return new Integer(getFirstObject());
			case ModelPackage.CCLASS__LAST_OBJECT:
				return new Integer(getLastObject());
			case ModelPackage.CCLASS__CARDINALITY:
				return getCardinality();
			case ModelPackage.CCLASS__SELF_CARDINALITY:
				return getSelfCardinality();
			case ModelPackage.CCLASS__COBJECTS:
				return getCObjects();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case ModelPackage.CCLASS__SUPER_CLASS:
				setSuperClass((CClass)newValue);
				return;
			case ModelPackage.CCLASS__SUB_CLASSES:
				getSubClasses().clear();
				getSubClasses().addAll((Collection<? extends CClass>)newValue);
				return;
			case ModelPackage.CCLASS__ABSTRACT:
				setAbstract(((Boolean)newValue).booleanValue());
				return;
			case ModelPackage.CCLASS__FIRST_OBJECT:
				setFirstObject(((Integer)newValue).intValue());
				return;
			case ModelPackage.CCLASS__LAST_OBJECT:
				setLastObject(((Integer)newValue).intValue());
				return;
			case ModelPackage.CCLASS__CARDINALITY:
				setCardinality((CIntVar)newValue);
				return;
			case ModelPackage.CCLASS__SELF_CARDINALITY:
				setSelfCardinality((CIntVar)newValue);
				return;
			case ModelPackage.CCLASS__COBJECTS:
				getCObjects().clear();
				getCObjects().addAll((Collection<? extends CObject>)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case ModelPackage.CCLASS__SUPER_CLASS:
				setSuperClass((CClass)null);
				return;
			case ModelPackage.CCLASS__SUB_CLASSES:
				getSubClasses().clear();
				return;
			case ModelPackage.CCLASS__ABSTRACT:
				setAbstract(ABSTRACT_EDEFAULT);
				return;
			case ModelPackage.CCLASS__FIRST_OBJECT:
				setFirstObject(FIRST_OBJECT_EDEFAULT);
				return;
			case ModelPackage.CCLASS__LAST_OBJECT:
				setLastObject(LAST_OBJECT_EDEFAULT);
				return;
			case ModelPackage.CCLASS__CARDINALITY:
				setCardinality((CIntVar)null);
				return;
			case ModelPackage.CCLASS__SELF_CARDINALITY:
				setSelfCardinality((CIntVar)null);
				return;
			case ModelPackage.CCLASS__COBJECTS:
				getCObjects().clear();
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case ModelPackage.CCLASS__SUPER_CLASS:
				return superClass != null;
			case ModelPackage.CCLASS__SUB_CLASSES:
				return subClasses != null && !subClasses.isEmpty();
			case ModelPackage.CCLASS__ABSTRACT:
				return abstract_ != ABSTRACT_EDEFAULT;
			case ModelPackage.CCLASS__FIRST_OBJECT:
				return firstObject != FIRST_OBJECT_EDEFAULT;
			case ModelPackage.CCLASS__LAST_OBJECT:
				return lastObject != LAST_OBJECT_EDEFAULT;
			case ModelPackage.CCLASS__CARDINALITY:
				return cardinality != null;
			case ModelPackage.CCLASS__SELF_CARDINALITY:
				return selfCardinality != null;
			case ModelPackage.CCLASS__COBJECTS:
				return cObjects != null && !cObjects.isEmpty();
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (abstract: ");
		result.append(abstract_);
		result.append(", firstObject: ");
		result.append(firstObject);
		result.append(", lastObject: ");
		result.append(lastObject);
		result.append(')');
		return result.toString();
	}
	
	/**
	 * @not generated
	 */
	public void initCCore(CCore core) {
		setCCore(core);
		
		getCardinality().initCCore(core);
		getSelfCardinality().initCCore(core);
	}

} //CClassImpl
